#include "Animation_H.h"
#include <iostream>
#include <conio.h>
using namespace std;



Animation::~Animation()
{
	list<Rectangl *>::iterator i;

	for(i=Ltemp.begin(); i != Ltemp.end(); ++i)
			delete *i;
}


void Animation::AnimationWithClashesPoly( list<Shape *> l, int drawingOption )
{
	 
	int dirX, dirY;
	int posX, posY;

	list<Shape *>::iterator i;
	list<Shape *>::iterator j;

	system("cls");

	oldScreen->resetScreenBuffer();
	newScreen->resetScreenBuffer();

	for(i=l.begin(); i != l.end(); ++i) // first printing into screen buffer;
			(*i)->draw(drawingOption,oldScreen);

	for(i=l.begin(); i != l.end(); ++i) // first printing into screen;
			(*i)->draw(drawingOption);

	do
	{
    
	  for(i=l.begin(); i != l.end(); ++i)
	  {
		
		if(!(*i)->isDirectionsResetBorders()) 
		{
			j = i;
			j++;
			for(j; j != l.end(); ++j)
	        {
			
			  if(typeid(*(*i)) == typeid(Rectangl)) 
			  {
				if(typeid(*(*j)) == typeid(Rectangl)) 
					isDirectionsResetRectangles(dynamic_cast<Rectangl *>(*i),dynamic_cast<Rectangl *>(*j));
				else if(typeid(*(*j)) == typeid(Circle)) isDirectionsResetRectanglesCircles(dynamic_cast<Rectangl *>(*i),dynamic_cast<Circle *>(*j));
			  }

			  else if(typeid(*(*i)) == typeid(Circle)) 
			  {
				  if(typeid(*(*j)) == typeid(Circle)) 
					  isDirectionsResetCircles(dynamic_cast<Circle *>(*i),dynamic_cast<Circle *>(*j));
				  else if(typeid(*(*j)) == typeid(Rectangl)) isDirectionsResetRectanglesCircles(dynamic_cast<Rectangl *>(*j),dynamic_cast<Circle *>(*i));
			  }
				else cout << "Unknown shape form";
			  
			}
		}
	
		(*i)->getIntegerDirection(dirX,dirY);
		(*i)->getPos(posX,posY); // getting the pos
		(*i)->setPos(posX+dirX,posY+dirY); // resetting the pos according to Borders reset
	  }
	 
	  for(i=l.begin(); i != l.end(); ++i) // first printing into scree buffer;
			(*i)->draw(drawingOption,newScreen);
	   
	  printingDiff();
	  Sleep(100);

	}while(!_kbhit());
	
 }


 void Animation::isDirectionsResetRectanglesCircles(Rectangl * r, Circle * c2)
 {
	 int recPosX, recPosY, cirPosX, cirPosY;
	 int recSizeX, recSizeY, cirSize;
	 int recDirX, recDirY, cirDirX, cirDirY;

	 Point p2Check;

	 r->getPos(recPosX,recPosY);
	 r->getSize(recSizeX,recSizeY);
	 r->getIntegerDirectionExplicitly(recDirX,recDirY);
	
	 c2->getPos(cirPosX,cirPosY);
	 c2->getSize(cirSize);
	 c2->getIntegerDirectionExplicitly(cirDirX,cirDirY);

	 bool hitX = false;
	 bool hitY = false;

	 for(int i=recPosX+1; i<recPosX+recSizeX-1; i++)
	 {
		 p2Check.setPos(i,recPosY);
		 if(c2->isPointInCircleEnvelop(p2Check,c2))
		 {
			 if(c2->isXaxis(p2Check))
			 {
				 if(abs(recDirY) > abs(cirDirY)) r->resetDirectionY();
				 else if (abs(recDirY) < abs(cirDirY)) c2->resetDirectionY();
				 else{
					 r->resetDirectionY();
					 c2->resetDirectionY();
				 }
			 
				
			   if(c2->isYaxis(p2Check)) c2->resetDirectionX();
			 }
		 

		   else if(c2->isYaxis(p2Check))
		   {
			  r->resetDirectionY();
			  c2->resetDirectionX();
		   }
		
		   else{
		 	   c2->resetDirectionX();
			   c2->resetDirectionY();
			   r->resetDirectionX();
		   }
		 
		 hitX = true;
		 }
	 }

			 
	 for(int i=recPosX+1; i<recPosX+recSizeX-1 && hitX == false; i++)
	 {
		 p2Check.setPos(i,recPosY+recSizeY-1);
		 if(c2->isPointInCircleEnvelop(p2Check,c2))
		 {
			 if(c2->isXaxis(p2Check))
			 {
				 if(abs(recDirY) > abs(cirDirY)) r->resetDirectionY();
				 else if (abs(recDirY) < abs(cirDirY)) c2->resetDirectionY();
				 else{
					 r->resetDirectionY();
					 c2->resetDirectionY();
				 }
			 
				
			   if(c2->isYaxis(p2Check)) c2->resetDirectionX();
			 }
		 

		   else if(c2->isYaxis(p2Check))
		   {
			  r->resetDirectionY();
			  c2->resetDirectionX();
		   }
		
		   else{
		 	   c2->resetDirectionX();
			   c2->resetDirectionY();
			   r->resetDirectionX();
		   }
		 
		 hitX = true;
		 }
	 }

	 
	 for(int i=recPosY+1; i<recPosY+recSizeY-1 && hitY == false; i++)
	 {
		 p2Check.setPos(recPosX,i);
		 if(c2->isPointInCircleEnvelop(p2Check,c2))
		 {
			 if(c2->isYaxis(p2Check))
			 {
				 if(abs(recDirX) > abs(cirDirX)) r->resetDirectionX();
				 else if (abs(recDirX) < abs(cirDirX)) c2->resetDirectionX();
				 else{
					 r->resetDirectionX();
					 c2->resetDirectionX();
				 }
			 
				
			   if(c2->isXaxis(p2Check)) c2->resetDirectionY();
			 }
		 

		   else if(c2->isXaxis(p2Check))
		   {
			  r->resetDirectionX();
			  c2->resetDirectionY();
		   }
		
		   else{
		 	   c2->resetDirectionX();
			   c2->resetDirectionY();
			   r->resetDirectionX();
		   }
		 
		 hitY = true;
		 }
	 }



	 for(int i=recPosY+1; i<recPosY+recSizeY-1 && hitY == false; i++)
	 {
		 p2Check.setPos(recPosX+recSizeX-1,i);
		 if(c2->isPointInCircleEnvelop(p2Check,c2))
		 {
			 if(c2->isYaxis(p2Check))
			 {
				 if(abs(recDirX) > abs(cirDirX)) r->resetDirectionX();
				 else if (abs(recDirX) < abs(cirDirX)) c2->resetDirectionX();
				 else{
					 r->resetDirectionX();
					 c2->resetDirectionX();
				 }
			 
				
			   if(c2->isXaxis(p2Check)) c2->resetDirectionY();
			 }
		 

		   else if(c2->isXaxis(p2Check))
		   {
			  r->resetDirectionX();
			  c2->resetDirectionY();
		   }
		
		   else{
		 	   c2->resetDirectionX();
			   c2->resetDirectionY();
			   r->resetDirectionX();
		   }
		 
		 hitY = true;
		 }
	 }

	 if(hitX == false && hitY == false)
	 {
		 p2Check.setPos(recPosX,recPosY);
		 if(c2->isPointInCircleEnvelop(p2Check,c2))
		 {
			  c2->resetDirectionX();
			  c2->resetDirectionY();
			  r->resetDirectionX();
			  r->resetDirectionY();
			  hitX = hitY = true;
		 }

		 p2Check.setPos(recPosX+recSizeX-1,recPosY);
		 if(c2->isPointInCircleEnvelop(p2Check,c2) && !hitX && !hitY)
		 {
			  c2->resetDirectionX();
			  c2->resetDirectionY();
			  r->resetDirectionX();
			  r->resetDirectionY();
			  hitX = hitY = true;
		 }


		 p2Check.setPos(recPosX,recPosY+recSizeY-1);
		 if(c2->isPointInCircleEnvelop(p2Check,c2) && !hitX && !hitX)
		 {
			  c2->resetDirectionX();
			  c2->resetDirectionY();
			  r->resetDirectionX();
			  r->resetDirectionY();
			  hitX = hitY = true;
		 }

		 p2Check.setPos(recPosX+recSizeX-1,recPosY+recSizeY-1);
		 if(c2->isPointInCircleEnvelop(p2Check,c2) && !hitX && !hitY)
		 {
			  c2->resetDirectionX();
			  c2->resetDirectionY();
			  r->resetDirectionX();
			  r->resetDirectionY();
			  hitX = hitY = true;
		 }

	 }

 }

void Animation::printingDiff() // printing the diff out of the screen buffer
{
	char c1, c2;
	Screen * temp;
	
	for(int i=0; i<=24; i++)
		for(int j=0; j<=79; j++)
		{
			c1 = oldScreen->getChar(j,i);
			c2 = newScreen->getChar(j,i);
			if(c2!=c1)
			{
      			gotoxy(j,i); cout << c2;			
			}
		}

		temp = oldScreen;
		oldScreen = newScreen;
		newScreen = temp;
		newScreen->resetScreenBuffer();
}

bool Animation::isDirectionsResetRectangles(Rectangl * r, Rectangl * i) // main func to check clashes between rectangles
{
	Point TL,BR;
	float rDirX, rDirY, iDirX, iDirY; 
	bool clashed = false;
	
	r->getOriginalDirection(rDirX,rDirY);
	i->getOriginalDirection(iDirX,iDirY);
	
	
		if  (r->isOverlap(i)) // Am I touching that Rectangle ?
		{ 
				
				if (i->isContaining(r)) isDirectionsResetRectangleBorders(r,i); // Is *i Rectangle includes me ?
				
		        else if (r->isContaining(i)) isDirectionsResetRectangleBorders(i,r); // So maybe I'm including it instead ?
					
				else
				{
						if(!isDirectionsResetRectangleWithRectangle(r,i)) // If not, So I must be clashing with it based on my direction
							if(!(isDirectionsResetRectangleWithRectangle(i,r))) // If not, So I maybe it clashing with me based on its direction
								if(!(isDirectionsResetRectangleWithRectanglePrevious(r,i))) // maybe we both entered one another without really touching ?
									if(!(isDirectionsResetRectangleWithRectanglePrevious(i,r))) // again .. maybe the above one
									{ 
										r->resetDirectionX();  // and if not change both directions, it aint a normal clash
										r->resetDirectionY();
										i->resetDirectionX();
										i->resetDirectionY();
									}
				}			          
			
				clashed = true;		
		
		}
		
	

	if(clashed) return true;

	return false;
}

bool Animation::isDirectionsResetRectangleWithRectanglePrevious(Rectangl * r, Rectangl * i) // sometimes when two rectangles set in motion towards one another,
{                                                                                          // there is a situation which they enter each other with really touching each rectangle borders
	int r_prevDirX, r_prevDirY;                                                           // so we are taking a step beck and checking clahses
	int r_posX, r_posY;
	
	r->getPrevDirection(r_prevDirX,r_prevDirY);
	r->getPos(r_posX,r_posY);
	r->setPos(r_posX-r_prevDirX,r_posY-r_prevDirY);

	if (r->isContaining(i))
	{
		isDirectionsResetRectangleBorders(i,r);
		r->setPos(r_posX+r_prevDirX,r_posY+r_prevDirY);
		return true;
	}

	else if(isDirectionsResetRectangleWithRectangle(r,i))
	{
		r->setPos(r_posX+r_prevDirX,r_posY+r_prevDirY);
		return true;
	}

	r->setPos(r_posX+r_prevDirX,r_posY+r_prevDirY);

	return false;
}

bool Animation::isDirectionsResetRectangleWithRectangle(Rectangl * r, Rectangl * i) // checking clashes between two rectangles which don't contain each other
{
	int r_dirX, r_dirY, i_dirX, i_dirY;
	int r_sizeX, r_sizeY, i_sizeX, i_sizeY;
	int r_posX, r_posY, i_posX, i_posY;
	float r_OdirX, r_OdirY, i_OdirX, i_OdirY;

	int flag = 0;
    bool clashed = false;
	

	r->getIntegerDirectionExplicitly(r_dirX,r_dirY);
	r->getPos(r_posX,r_posY);
	r->getSize(r_sizeX,r_sizeY);
	i->getPos(i_posX,i_posY);
	i->getSize(i_sizeX,i_sizeY);
	i->getIntegerDirectionExplicitly(i_dirX,i_dirY);

	r->getOriginalDirection(r_OdirX,r_OdirY);
	i->getOriginalDirection(i_OdirX,i_OdirY);

	if(r_OdirY < 0)
	{
		for(int k=r_posX; k < r_posX + r_sizeX && flag==0; k++)
		{
			for(int j=i_posX; j < i_posX + i_sizeX && flag==0; j++)
			{
				if(k==j &&  r_posY == i_posY + i_sizeY - 1)
				{
					if(i_OdirY < 0)
					{
						if(r_OdirY < i_OdirY)
						r->resetDirectionY();
		                else
			            i->resetDirectionY();
					}

					else
					{
						r->resetDirectionY();
						i->resetDirectionY();
					}
				
			    clashed = true;
				flag++;
				}
			}
		}
	}

	else if(r_OdirY > 0)
	{
		
		for(int k=r_posX; k < r_posX + r_sizeX && flag==0; k++)
		{
			for(int j=i_posX; j < i_posX + i_sizeX && flag==0; j++)
			{
				if(k==j &&  r_posY + r_sizeY - 1 == i_posY)
				{
					if(i_OdirY > 0)
					{
						if(r_OdirY > i_OdirY)
						r->resetDirectionY();
		                else
			            i->resetDirectionY();
					}

					else
					{
						r->resetDirectionY();
						i->resetDirectionY();
					}

				clashed = true;
				flag++;
				}
			}
		}
	}

	flag = 0;
	if(r_OdirX < 0)
	{
		for(int k=r_posY; k < r_posY + r_sizeY && flag==0; k++)
		{
			for(int j=i_posY; j < i_posY + i_sizeY && flag==0; j++)
			{
				if(k==j &&  r_posX == i_posX + i_sizeX -1)
				{
					if(i_OdirX < 0)
					{
						if(r_OdirX < i_OdirX)
						r->resetDirectionX();
		                else
			            i->resetDirectionX();
					}

					else
					{
						r->resetDirectionX();
						i->resetDirectionX();
					}
                
			    clashed = true;
				flag++;
				}
			}
		}
	}

	else if(r_OdirX > 0)
	{
		for(int k=r_posY; k < r_posY + r_sizeY && flag==0; k++)
		{
			for(int j=i_posY; j < i_posY + i_sizeY && flag==0; j++)
			{
				if(k==j &&  r_posX + r_sizeX - 1 == i_posX)
				{
					if(i_OdirX > 0)
					{
						if(r_OdirX > i_OdirX)
						r->resetDirectionX();
		                else
			            i->resetDirectionX();
					}

					else
					{	
						r->resetDirectionX();
						i->resetDirectionX();
					}

                clashed = true;
				flag++;
				}
			}
		}
	}


	if(clashed) return true;

	return false;

}

void Animation::getPosPointByDirection(int &r_posX, int &r_posY, int r_dir_x, int r_dir_y, Rectangl * r) // Which Main Position (TL/TR/BL/BR) am I pointing at ?
{
	
	int r_sizeX, r_sizeY, r_TLposX, r_TLposY;

	r->getPos(r_TLposX,r_TLposY);
	r->getSize(r_sizeX,r_sizeY);

	if(r_dir_x>=0){
		if(r_dir_y>=0) // BR
		{
			r_posX = r_TLposX + r_sizeX-1;
			r_posY = r_TLposY + r_sizeY-1;
		}
		else{  // TL
			r_posX = r_TLposX + r_sizeX-1;
			r_posY = r_TLposY;
		}
	}

    else{
		if(r_dir_y>0) // BL 
		{
				r_posX = r_TLposX;
				r_posY = r_TLposY + r_sizeY-1;
		}
		else{ // TR
			r_posX = r_TLposX;
			r_posY = r_TLposY;
		}
				
	}
}


void Animation::isDirectionsResetRectangleBordersCheckLimits(int r_posX, int r_posY, int r_dir_x, int r_dir_y, Rectangl * r, Rectangl * i)
{
	int max_limit_x, max_limit_y, min_limit_x, min_limit_y;
    float rDirX, rDirY, iDirX, iDirY; 

	calculateMaxMinBorders(i,max_limit_x,max_limit_y,min_limit_x,min_limit_y);

	r->getOriginalDirection(rDirX,rDirY);
	i->getOriginalDirection(iDirX,iDirY);	
	
	if(r_posX+r_dir_x > max_limit_x || r_posX+r_dir_x < min_limit_x) { 
		
		if(rDirX > 0 && iDirX > 0)
		{
		  if(rDirX > iDirX)
		 
			  r->resetDirectionX();
		  
		  else 
	      
			  i->resetDirectionX();
		}

		else if(rDirX < 0 && iDirX < 0)
		{
		  if(rDirX < iDirX)
		  r->resetDirectionX();  
		  else 
	      i->resetDirectionX();
		}

		else{
			 r->resetDirectionX();
			 i->resetDirectionX();
		}
	}


	if(r_posY+r_dir_y > max_limit_y || r_posY+r_dir_y < min_limit_y) { 
		
		if(rDirY > 0 && iDirY > 0)
		{
		  if(rDirY > iDirY)
		  r->resetDirectionY();
		  else 
	      i->resetDirectionY();
		}

		else if(rDirY < 0 && iDirY < 0)
		{
		  if(rDirY < iDirY)
		  r->resetDirectionY();
		  else 
	      i->resetDirectionY();
		}

		else{
			 r->resetDirectionY();
			 i->resetDirectionY();
		}	
	}

}

void Animation::isDirectionsResetRectangleBorders(Rectangl * r, Rectangl * i) // Checks clashes with rectangle borders
{
	int r_posX, r_posY,
		r_dir_x, r_dir_y,
		r_sizeX, r_sizeY;

	r->getIntegerDirectionExplicitly(r_dir_x,r_dir_y);

	if(r_dir_x != 0 && r_dir_y !=0) {
		
		getPosPointByDirection(r_posX,r_posY,r_dir_x,r_dir_y,r);
	    isDirectionsResetRectangleBordersCheckLimits(r_posX, r_posY, r_dir_x, r_dir_y,r,i);
	}

	else
	{
		r->getPos(r_posX,r_posY);
		r->getSize(r_sizeX,r_sizeY);
		isDirectionsResetRectangleBordersCheckLimits(r_posX-1, r_posY-1, r_dir_x, r_dir_y,r,i);
		isDirectionsResetRectangleBordersCheckLimits(r_posX+r_sizeX, r_posY+r_sizeY, r_dir_x, r_dir_y,r,i);
	}


}

void Animation::calculateMaxMinBorders(Rectangl * r, int &max_limit_x, int &max_limit_y, int &min_limit_x, int &min_limit_y) // Calculates the max limit per rectangle for rectangle border func
{
	int x,y;
	int sizeX, sizeY;
	
	r->getPos(x,y);
	r->getSize(sizeX,sizeY);

	max_limit_x = x + sizeX-1;
    max_limit_y = y + sizeY-1;
	min_limit_x = x;
	min_limit_y = y;

}

bool Animation::isDirectionsResetBorders(Rectangl * r) // Checks clashes with screen borders
{
	int r_posX, r_posY;
	bool chengeMade = false;
	int dirX, dirY;

	r->getIntegerDirectionExplicitly(dirX,dirY);

    getPosPointByDirection(r_posX,r_posY,dirX,dirY,r);

	if(r_posX+dirX > MAX_SCR_WIDTH+1 || r_posX+dirX < MIN_SCR_WIDTH-1) { 

		r->resetDirectionX();
		dirX = -dirX; 
		chengeMade = true;
	}

	if(r_posY+dirY > MAX_SCR_LEN+1 || r_posY+dirY < MIN_SCR_LEN-1) { 
		
		r->resetDirectionY();
		dirY = -dirY;
		chengeMade = true;
	}

    if(chengeMade) return true;

	return false;
	  
}


int Animation::inBorder(Rectangl * r){

	Point tmp;
	int counter = 0;
	// Possible Return values {0,3,7,5,10,11,12,13,14,15}
	// Each value represent the position of the rectangle in the screen
	// return "counter" as the sum of the Points that are not in the screen
	/*
	INDEX - SCREEN POSITION
	For Example : MID_UP
	TL = 1
	TR = 2
	BL = 4
	BR = 8

	*TL & TR are outside of the screen therefore : 1+2 = 3 = MID_UP
	   TL---TR
		|	|
	=============
	=	|	|	=
	=  BL---BR	=
	=			=
	=============
	0 - ENTIRELY INSIDE
	3 - MID_UP
	5 - MID_LEFT
	7 - UP_LEFT
	10 - MID_RIGHT
	11 - UP_RIGHT
	12 - MID_DOWN
	13 - DOWN_LEFT
	14 - DOWN_RIGHT
	15 - ENTIRELY OUTSIDE
	*/

	tmp = r->getPointTL();
	if (!isInBorder(&tmp))
		counter+=1;

	tmp = r->getPointTR();
	if (!isInBorder(&tmp))
		counter+=2;

	tmp = r->getPointBL();
	if (!isInBorder(&tmp))
		counter+=4;

	tmp = r->getPointBR();
	if (!isInBorder(&tmp))
		counter+=8;
	
	return counter;

}

bool Animation::isInBorder(Point *p){

	int x,y;

	p->getPos(x,y);

	if(x>MAX_SCR_WIDTH || y > MAX_SCR_LEN)
		return false;
	
	if(x<0 || y<0)
		return false;

	return true;

}

void Animation::createCopiedTempList(const list<Rectangl *> & l)
{
	list<Rectangl *>::const_iterator i;

	for(i=l.begin(); i != l.end(); ++i)
	{
		Rectangl * newRectangle = new Rectangl;
		*newRectangle = *(*i);
		Ltemp.push_back(newRectangle);
	}

}


void Animation::createCopiedTempListCircles(const list<Circle *> & l)
{
	list<Circle *>::const_iterator i;

	for(i=l.begin(); i != l.end(); ++i)
	{
		Circle * newRectangle = new Circle;
		*newRectangle = *(*i);
		LtempCircles.push_back(newRectangle);
	}

}




bool Animation::isDirectionsResetCircles(Circle * c, Circle * c2)
{
			
		isDirectionsResetCircleClahsedWithCircle(c,c2);


	return true;
}


void Animation::isDirectionsResetCircleClahsedWithCircle(Circle * c, Circle * c2)
{
	Point hitPoint;
	int c1dirX, c1dirY, c2dirX, c2dirY;

	if(c->getHitPoint(c2,hitPoint)){
		
		c->getIntegerDirectionExplicitly(c1dirX,c1dirY);
		c2->getIntegerDirectionExplicitly(c2dirX,c2dirY);
		
	
		if(c->isXaxis(hitPoint) || c2->isXaxis(hitPoint))
		{
			if((c->isXaxis(hitPoint) && c2->isXaxis(hitPoint)))
			{
				if(abs(c1dirX) > abs(c2dirX)) c->resetDirectionX();
				else if(c1dirX < c2dirX) c2->resetDirectionX();
				else{
					c->resetDirectionX();
					c2->resetDirectionX();
				}
			}

			else if(c->isXaxis(hitPoint)) c->resetDirectionX();
			else c2->resetDirectionX();
		}
			
		if(c->isYaxis(hitPoint) || c2->isYaxis(hitPoint))
		{
			if(c->isYaxis(hitPoint) && c2->isYaxis(hitPoint))
			{
				if(abs(c1dirY) > abs(c2dirY)) c->resetDirectionY();
				else if(c1dirY < c2dirY) c2->resetDirectionY();
				else{
					c->resetDirectionY();
					c2->resetDirectionY();
				}
			}

			else if(c->isYaxis(hitPoint)) c->resetDirectionY();
			else c2->resetDirectionY();
		}
	}

}

void Animation::addTimeToShapeAnim(list<Shape*> &lst)
{
	list<Shape*>::iterator i;

	for (i = lst.begin(); i != lst.end(); ++i)
	{
		(*i)->addSumDirX();
		(*i)->addSumDirY();
	}
}


void Animation::initSum(list<Shape*> &lst)
{
	list<Shape*>::iterator i;

	for (i = lst.begin(); i != lst.end(); ++i)
	{
		(*i)->initSum(); //zero the movement SUM if moved
	}
}




void Animation::AnimationWithoutClashesPoly(list<Shape *> & lst, int drawingOption)
{

	list<Shape *>::iterator i;

	oldScreen->resetScreenBuffer();
	newScreen->resetScreenBuffer();

	system("cls");

	for(i=lst.begin(); i != lst.end(); ++i) // first printing into screen buffer;
			(*i)->draw(drawingOption,oldScreen);

	for(i=lst.begin(); i != lst.end(); ++i) // first printing into screen;
			(*i)->draw(drawingOption);

	do
	{
		for(i=lst.begin(); i != lst.end(); ++i) 
		{
			if(typeid(*(*i)) == typeid(Rectangl)) 
			{
				 printRectanglWithoutClashes(dynamic_cast<Rectangl*>(*i));
			}
			if(typeid(*(*i)) == typeid(Circle))
			{
				printCircleWithoutClashes(dynamic_cast<Circle*>(*i));
			}

		}

		printingDiff();
		Sleep(100);

	}while(!_kbhit());
		
}

void Animation::printRectanglWithoutClashes(Rectangl * r)
{


	int dirX, dirY;
	int posX, posY;
	int sizeX, sizeY;
	int posXTemp, posYTemp;

	Point pTemp;

	list<Shape *>::iterator i;

	r->getPos(posX,posY);
	r->getSize(sizeX,sizeY);
	
	for(int j=posX; j < posX+sizeX; j++)
	{
		pTemp.setPos(j,posY);
		if(!isInScreen(pTemp)) AnimationWithoutClashesPolyHelper(j,posY);
		else newScreen->setToScreenBuffer(posY,j);
	}

	for(int j=posX; j < posX+sizeX; j++)
	{
		pTemp.setPos(j,posY+sizeY-1);
		if(!isInScreen(pTemp)) AnimationWithoutClashesPolyHelper(j,posY+sizeY-1);
		else newScreen->setToScreenBuffer(posY+sizeY-1,j);
	}

	for(int j=posY; j < posY+sizeY; j++)
	{
		pTemp.setPos(posX,j);
		if(!isInScreen(pTemp)) AnimationWithoutClashesPolyHelper(posX,j);
		else newScreen->setToScreenBuffer(j,posX);
	}
	
	for(int j=posY; j < posY+sizeY; j++)
	{
		pTemp.setPos(posX+sizeX-1,j);
		if(!isInScreen(pTemp)) AnimationWithoutClashesPolyHelper(posX+sizeX-1,j);
		else newScreen->setToScreenBuffer(j,posX+sizeX-1);
	}

	r->getIntegerDirection(dirX,dirY);
    r->getPos(posX,posY); // getting the pos
	r->setPos(posX+dirX,posY+dirY); // resetting the pos according to Borders reset

	posXTemp = (posX+sizeX+posX)/2;
	posYTemp = (posY+sizeY+posY)/2;
	
	if(posXTemp > MAX_SCREEN_X && posYTemp > MAX_SCREEN_Y)
		r->setPos(posX%79,posY%MAX_SCREEN_Y);
	
	
	if(posXTemp < 0 && posYTemp > MAX_SCREEN_Y)
		r->setPos(posX%79+79,posY%MAX_SCREEN_Y);
	

	if(posXTemp > MAX_SCREEN_X && posYTemp < 0)
		r->setPos(posX%79,posY%MAX_SCREEN_Y+MAX_SCREEN_Y);

	if(posXTemp < 0 && posYTemp < 0)
		r->setPos(posX%79+79,posY%MAX_SCREEN_Y+MAX_SCREEN_Y);
}

void Animation::AnimationWithoutClashesPolyHelper(int x, int y)
{
	Point pTemp;
	
	if(y >= MAX_SCREEN_Y){ pTemp.setPos(x,y%MAX_SCREEN_Y);  if(isInScreen(pTemp)) newScreen->setToScreenBuffer(y%MAX_SCREEN_Y,x);}
	if(y <= 0) { pTemp.setPos(x,y%MAX_SCREEN_Y+MAX_SCREEN_Y);  if(isInScreen(pTemp)) newScreen->setToScreenBuffer(y%MAX_SCREEN_Y+MAX_SCREEN_Y,x);}
	if(x >= MAX_SCREEN_X){ pTemp.setPos(x%79,y);  if(isInScreen(pTemp)) newScreen->setToScreenBuffer(y,x%79);}
	if(x <= 0) { pTemp.setPos(x%79+79,y);  if(isInScreen(pTemp)) newScreen->setToScreenBuffer(y,x%79+79);}
}


void Animation::printCircleWithoutClashes(Circle * c)
{
	int circleX, circleY;
	int radius;

	int x,y;

	int dirX, dirY;
	int posX, posY;

	Point p1,p2,p3,p4;

	c->getPos(circleX,circleY);
	c->getSize(radius);

	list<Shape *>::iterator i;

	int checking = -radius;
	int xC = radius;
	int yC = 0;

	while (xC >= yC)
	{  
		 c->get4Points(circleX, circleY, xC, yC, p1, p2, p3, p4);
		 {
			 p1.getPos(x,y);
			 if(!isInScreen(p1)) AnimationWithoutClashesPolyHelper(x,y);
			 else newScreen->setToScreenBuffer(y,x);

			 p2.getPos(x,y);
			 if(!isInScreen(p2)) AnimationWithoutClashesPolyHelper(x,y);
			 else newScreen->setToScreenBuffer(y,x);

			 p3.getPos(x,y);
			 if(!isInScreen(p3)) AnimationWithoutClashesPolyHelper(x,y);
			 else newScreen->setToScreenBuffer(y,x);

			 p4.getPos(x,y);
			 if(!isInScreen(p4)) AnimationWithoutClashesPolyHelper(x,y);
			 else newScreen->setToScreenBuffer(y,x);			 
		 }


		 if(x!=y)
		 {
			 c->get4Points(circleX, circleY, yC, xC, p1, p2, p3, p4);

			p1.getPos(x,y);
			 if(!isInScreen(p1)) AnimationWithoutClashesPolyHelper(x,y);
			 else newScreen->setToScreenBuffer(y,x);

			 p2.getPos(x,y);
			 if(!isInScreen(p2)) AnimationWithoutClashesPolyHelper(x,y);
			 else newScreen->setToScreenBuffer(y,x);

			 p3.getPos(x,y);
			 if(!isInScreen(p3)) AnimationWithoutClashesPolyHelper(x,y);
			 else newScreen->setToScreenBuffer(y,x);

			 p4.getPos(x,y);
			 if(!isInScreen(p4)) AnimationWithoutClashesPolyHelper(x,y);
			 else newScreen->setToScreenBuffer(y,x);
		}

		 checking += yC;
         ++yC;
         checking += yC;
 
         if (checking >= 0)
         {
            checking -= xC;
            --xC;
            checking -= xC;
         }
	}

	c->getIntegerDirection(dirX,dirY);
    c->getPos(posX,posY); // getting the pos
	c->setPos(posX+dirX,posY+dirY); // resetting the pos according to Borders reset

	
	if(posX > MAX_SCREEN_X && posY > MAX_SCREEN_Y)
		c->setPos(posX%79,posY%MAX_SCREEN_Y);
	
	if(posX < 0 && posY > MAX_SCREEN_Y)
		c->setPos(posX%79+79,posY%MAX_SCREEN_Y);

	if(posX > MAX_SCREEN_X && posY < 0)
		c->setPos(posX%79,posY%MAX_SCREEN_Y+MAX_SCREEN_Y);

	if(posX < 0 && posY < 0)
		c->setPos(posX%79+79,posY%MAX_SCREEN_Y+MAX_SCREEN_Y);
	
}


bool Animation::isInScreen(Point p2)
{
	int x,y;
	
	p2.getPos(x,y);

	if( x >=0 && x <= MAX_SCR_WID-1)
		if (y >= 0 && y <= MAX_SCR_LEN-1)
			return true;
		
	return false;
}
